package com.ifonly.common.typeconverter;

/**
 * @author <a href="mailto:ifonlymaster@163.com">ifonly</a>
 * @version 1.0 2015-12-17 16:47
 * @since JDK 1.6
 */

import com.ifonly.common.typeconverter.impl.*;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;

public class TypeConvert {

    private static final HashMap<Class, Converter> converters = new HashMap<Class, Converter>(70) {
        private static final long serialVersionUID = 1264308468677605050L;

        {
            put(Boolean.class,          new BooleanConverter());
            put(boolean.class,          new BooleanConverter());

            put(Integer.class,          new IntegerConverter());
            put(int.class,              new IntegerConverter());

            put(Long.class,             new LongConverter());
            put(long.class,             new LongConverter());

            put(Float.class,            new FloatConverter());
            put(float.class,            new FloatConverter());

            put(Double.class,           new DoubleConverter());
            put(double.class,           new DoubleConverter());

            put(Short.class,            new ShortConverter());
            put(short.class,            new ShortConverter());

            put(Character.class,        new CharacterConverter());
            put(char.class,             new CharacterConverter());

            put(Byte.class,             new ByteConverter());
            put(byte.class,             new ByteConverter());


            put(Boolean[].class,        new ArrayConverter<Boolean>(Boolean.class));
            put(boolean[].class,        new BooleanArrayConverter());

            put(Byte[].class,           new ArrayConverter<Byte>(Byte.class));
            put(byte[].class,           new ByteArrayConverter());

            put(Integer[].class,        new ArrayConverter<Integer>(Integer.class));
            put(int[].class,            new IntegerArrayConverter());

            put(Long[].class,           new ArrayConverter<Long>(Long.class));
            put(long[].class,           new LongArrayConverter());

            put(Float[].class,          new ArrayConverter<Float>(Float.class));
            put(float[].class,          new FloatArrayConverter());

            put(Double[].class,         new ArrayConverter<Double>(Double.class));
            put(double[].class,         new DoubleArrayConverter());

            put(Short[].class,          new ArrayConverter<Short>(Short.class));
            put(short[].class,          new ShortArrayConverter());

            put(Character[].class,      new ArrayConverter<Character>(Character.class));
            put(char[].class, new CharacterArrayConverter());

            put(String.class, new StringConverter());
            put(String[].class, new StringArrayConverter());

            put(Class.class, new ClassConverter());
            put(Class[].class, new ClassArrayConverter());

            put(Date.class, new DateConverter());
            put(Calendar.class, new CalendarConverter());

            put(BigInteger.class, new BigIntegerConverter());
            put(BigDecimal.class, new BigDecimalConverter());
        }
    };


    @SuppressWarnings("unchecked")
    public static <T> T convert(Class<T> type, Object value) {
        Converter<T> converter = getConverter(type);
        if (converter == null) {
            throw new IllegalArgumentException("no such Converter for type " + type);
        }
        return converter.convert(value);
    }

    public static Converter getConverter(Class type) {
        return converters.get(type);
    }

    public static void register(Class type, Converter typeConverter) {
        converters.put(type, typeConverter);
    }

    // ---------------------------------------------------------------- @@generated

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Boolean & boolean

    /**
     * 转换成 Boolean 类型的数据
     *
     * @param value 需要处理的数据
     * @return 转换后的数据
     */
    public static Boolean toBoolean(Object value) {
        return (Boolean) converters.get(Boolean.class).convert(value);
    }

    /**
     * 转换成 Boolean 类型的数据
     *
     * @param value        需要处理的数据
     * @param defaultValue 默认值
     * @return 转换后的数据
     */
    public static Boolean toBoolean(Object value, Boolean defaultValue) {
        Boolean result = (Boolean) converters.get(Boolean.class).convert(value);
        if (result == null) {
            return defaultValue;
        }
        return result;
    }

    /**
     * 转换成 boolean 值
     *
     * @param value        需要转换的数据
     * @param defaultValue 默认值
     * @return 转换后的数据
     */
    public static boolean toBooleanValue(Object value, boolean defaultValue) {
        Converter converter = converters.get(boolean.class);
        Boolean result = (Boolean) converter.convert(value);
        if (result == null) {
            return defaultValue;
        }
        return result;
    }

    /**
     * 转换成 boolean 值
     *
     * @param value 需要转换的数据
     * @return 转换后的数据
     */
    public static boolean toBooleanValue(Object value) {
        return toBooleanValue(value, false);
    }

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Integer & int

    /**
     * 转换成 Integer 类型数据
     *
     * @param value 需要处理的值
     * @return 转后的值
     */
    public static Integer toInteger(Object value) {
        return (Integer) converters.get(Integer.class).convert(value);
    }

    /**
     * 转换成 Integer 类型数据
     *
     * @param value        需要处理的值
     * @param defaultValue 默认值
     * @return 转后的值
     */
    public static Integer toInteger(Object value, Integer defaultValue) {
        Integer result = (Integer) converters.get(Integer.class).convert(value);
        if (result == null) {
            return defaultValue;
        }
        return result;
    }

    /**
     * 转换成 int 类型数据
     *
     * @param value        需要处理的值
     * @param defaultValue 默认值
     * @return 转后的值
     */
    public static int toIntValue(Object value, int defaultValue) {
        Integer result = (Integer) converters.get(int.class).convert(value);
        if (result == null) {
            return defaultValue;
        }
        return result;
    }

    /**
     * 转换成 int 类型数据, 默认为0
     *
     * @param value 需要处理的值
     * @return 转后的值
     */
    public static int toIntValue(Object value) {
        return toIntValue(value, 0);
    }


    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Long & long

    /**
     * 转换为 Long 类型
     *
     * @param value 需要处理的值
     * @return 转换后的值
     */
    public static Long toLong(Object value) {
        return (Long) converters.get(Long.class).convert(value);
    }

    /**
     * 转换为 Long 类型
     *
     * @param value        需要处理的值
     * @param defaultValue 默认值
     * @return 转换后的值
     */
    public static Long toLong(Object value, Long defaultValue) {
        Long result = (Long) converters.get(Long.class).convert(value);
        if (result == null) {
            return defaultValue;
        }
        return result;
    }

    /**
     * 转换为 long 类型
     *
     * @param value        需要处理的值
     * @param defaultValue 默认值
     * @return 转换后的值
     */
    public static long toLongValue(Object value, long defaultValue) {
        Long result = (Long) converters.get(long.class).convert(value);
        if (result == null) {
            return defaultValue;
        }
        return result;
    }

    /**
     * 转换为 long 类型
     *
     * @param value 需要处理的值
     * @return 转换后的值
     */
    public static long toLongValue(Object value) {
        return toLongValue(value, 0);
    }

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Float & float

    /**
     * 转换为 Float 类型
     *
     * @param value 需要处理的值
     * @return 转换后的值
     */
    public static Float toFloat(Object value) {
        return (Float) converters.get(Float.class).convert(value);
    }

    /**
     * 转换为 Float 类型
     *
     * @param value        需要处理的值
     * @param defaultValue 默认值
     * @return 转换后的值
     */
    public static Float toFloat(Object value, Float defaultValue) {
        Float result = (Float) converters.get(Float.class).convert(value);
        if (result == null) {
            return defaultValue;
        }
        return result;
    }

    /**
     * 转换为 float 值
     *
     * @param value        需要处理的值
     * @param defaultValue 默认值
     * @return 转换后的值
     */
    public static float toFloatValue(Object value, float defaultValue) {
        Float result = (Float) converters.get(float.class).convert(value);
        if (result == null) {
            return defaultValue;
        }
        return result;
    }

    /**
     * 转换为 float 值
     *
     * @param value 需要处理的值
     * @return 转换后的值
     */
    public static float toFloatValue(Object value) {
        return toFloatValue(value, 0);
    }

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Double & double

    /**
     * 转换为 Double 类型
     *
     * @param value 需要处理的值
     * @return 转换后的值
     */
    public static Double toDouble(Object value) {
        return (Double) converters.get(Double.class).convert(value);
    }

    /**
     * 转换为 Double 类型
     *
     * @param value        需要处理的值
     * @param defaultValue 默认值
     * @return 转换后的值
     */
    public static Double toDouble(Object value, Double defaultValue) {
        Double result = (Double) converters.get(Double.class).convert(value);
        if (result == null) {
            return defaultValue;
        }
        return result;
    }

    /**
     * 转换为 double 值
     *
     * @param value        需要处理的值
     * @param defaultValue 默认值
     * @return 转换后的值
     */
    public static double toDoubleValue(Object value, double defaultValue) {
        Double result = (Double) converters.get(double.class).convert(value);
        if (result == null) {
            return defaultValue;
        }
        return result;
    }

    /**
     * 转换为 double 值
     *
     * @param value 需要处理的值
     * @return 转换后的值
     */
    public static double toDoubleValue(Object value) {
        return toDoubleValue(value, 0);
    }

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Short & short

    /**
     * 转换为 Short 类型
     *
     * @param value 需要处理的值
     * @return 转换后的值
     */
    public static Short toShort(Object value) {
        return (Short) converters.get(Short.class).convert(value);
    }

    /**
     * 转换为 Short 类型
     *
     * @param value        需要处理的值
     * @param defaultValue 默认值
     * @return 转换后的值
     */
    public static Short toShort(Object value, Short defaultValue) {
        Short result = (Short) converters.get(Short.class).convert(value);
        if (result == null) {
            return defaultValue;
        }
        return result;
    }

    /**
     * 转换为 short 值
     *
     * @param value        需要处理的值
     * @param defaultValue 默认值
     * @return 转换后的值
     */
    public static short toShortValue(Object value, short defaultValue) {
        Short result = (Short) converters.get(short.class).convert(value);
        if (result == null) {
            return defaultValue;
        }
        return result;
    }

    /**
     * 转换为 short 值
     *
     * @param value 需要处理的值
     * @return 转换后的值
     */
    public static short toShortValue(Object value) {
        return toShortValue(value, (short) 0);
    }

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Character & char

    /**
     * 转换为 Character 类型
     *
     * @param value 需要处理的值
     * @return 转换后的值
     */
    public static Character toCharacter(Object value) {
        return (Character) converters.get(Character.class).convert(value);
    }

    /**
     * 转换为 Character 类型
     *
     * @param value        需要处理的值
     * @param defaultValue 默认值
     * @return 转换后的值
     */
    public static Character toCharacter(Object value, Character defaultValue) {
        Character result = (Character) converters.get(Character.class).convert(value);
        if (result == null) {
            return defaultValue;
        }
        return result;
    }

    /**
     * 转换为 char 值
     *
     * @param value        需要处理的值
     * @param defaultValue 默认值
     * @return 转换后的值
     */
    public static char toCharValue(Object value, char defaultValue) {
        Character result = (Character) converters.get(char.class).convert(value);
        if (result == null) {
            return defaultValue;
        }
        return result;
    }

    /**
     * 转换为 char 值
     *
     * @param value 需要处理的值
     * @return 转换后的值
     */
    public static char toCharValue(Object value) {
        return toCharValue(value, (char) 0);
    }

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Byte & byte

    /**
     * 转换为 Byte 类型
     *
     * @param value 需要处理的值
     * @return 转换后的值
     */
    public static Byte toByte(Object value) {
        return (Byte) converters.get(Byte.class).convert(value);
    }

    /**
     * 转换为 Byte 类型
     *
     * @param value        需要处理的值
     * @param defaultValue 默认值
     * @return 转换后的值
     */
    public static Byte toByte(Object value, Byte defaultValue) {
        Byte result = (Byte) converters.get(Byte.class).convert(value);
        if (result == null) {
            return defaultValue;
        }
        return result;
    }

    /**
     * 转换为 byte 值
     *
     * @param value        需要处理的值
     * @param defaultValue 默认值
     * @return 转换后的值
     */
    public static byte toByteValue(Object value, byte defaultValue) {
        Byte result = (Byte) converters.get(byte.class).convert(value);
        if (result == null) {
            return defaultValue;
        }
        return result;
    }

    /**
     * 转换为 byte 值
     *
     * @param value 需要处理的值
     * @return 转换后的值
     */
    public static byte toByteValue(Object value) {
        return toByteValue(value, (byte) 0);
    }

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Basic data type arrays

    /**
     * boolean[]
     *
     * @param value 需要处理的值
     * @return 转换后的值
     */
    public static boolean[] toBooleanArray(Object value) {
        return (boolean[]) converters.get(boolean[].class).convert(value);
    }

    /**
     * int[]
     *
     * @param value 需要处理的值
     * @return 转换后的值
     */
    public static int[] toIntegerArray(Object value) {
        return (int[]) converters.get(int[].class).convert(value);
    }

    /**
     * long[]
     *
     * @param value 需要处理的值
     * @return 转换后的值
     */
    public static long[] toLongArray(Object value) {
        return (long[]) converters.get(long[].class).convert(value);
    }

    /**
     * float[]
     *
     * @param value 需要处理的值
     * @return 转换后的值
     */
    public static float[] toFloatArray(Object value) {
        return (float[]) converters.get(float[].class).convert(value);
    }

    /**
     * double[]
     *
     * @param value 需要处理的值
     * @return 转换后的值
     */
    public static double[] toDoubleArray(Object value) {
        return (double[]) converters.get(double[].class).convert(value);
    }

    /**
     * short[]
     *
     * @param value 需要处理的值
     * @return 转换后的值
     */
    public static short[] toShortArray(Object value) {
        return (short[]) converters.get(short[].class).convert(value);
    }

    /**
     * char[]
     *
     * @param value 需要处理的值
     * @return 转换后的值
     */
    public static char[] toCharacterArray(Object value) {
        return (char[]) converters.get(char[].class).convert(value);
    }

    /**
     * byte[]
     *
     * @param value 需要处理的值
     * @return 转换后的值
     */
    public static byte[] toByteArray(Object value) {
        return (byte[]) converters.get(byte[].class).convert(value);
    }

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ String & String array

    /**
     * String
     *
     * @param value 需要处理的值
     * @return 转换后的值
     */
    public static String toString(Object value) {
        return (String) converters.get(String.class).convert(value);
    }

    /**
     * String
     *
     * @param value        需要处理的值
     * @param defaultValue 默认值
     * @return 转换后的值
     */
    public static String toString(Object value, String defaultValue) {
        String result = (String) converters.get(String.class).convert(value);
        if (result == null) {
            return defaultValue;
        }
        return result;
    }

    /**
     * String[]
     *
     * @param value 需要处理的值
     * @return 转换后的值
     */
    public static String[] toStringArray(Object value) {
        return (String[]) converters.get(String[].class).convert(value);
    }

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Class & Class array

    /**
     * Class
     *
     * @param value 需要处理的值
     * @return 转换后的值
     */
    public static Class toClass(Object value) {
        return (Class) converters.get(Class.class).convert(value);
    }

    /**
     * Class[]
     *
     * @param value 需要处理的值
     * @return 转换后的值
     */
    public static Class[] toClassArray(Object value) {
        return (Class[]) converters.get(Class[].class).convert(value);
    }

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Date

    /**
     * Date
     *
     * @param value 需要处理的值
     * @return 转换后的值
     */
    public static Date toDate(Object value) {
        return (Date) converters.get(Date.class).convert(value);
    }

    /**
     * Date
     *
     * @param value        需要处理的值
     * @param defaultValue 默认值
     * @return 转换后的值
     */
    public static Date toDate(Object value, Date defaultValue) {
        Date result = (Date) converters.get(Date.class).convert(value);
        if (result == null) {
            return defaultValue;
        }
        return result;
    }

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Calendar

    /**
     * Calendar
     *
     * @param value 需要处理的值
     * @return 转换后的值
     */
    public static Calendar toCalendar(Object value) {
        return (Calendar) converters.get(Calendar.class).convert(value);
    }

    /**
     * Calendar
     *
     * @param value        需要处理的值
     * @param defaultValue 默认值
     * @return 转换后的值
     */
    public static Calendar toCalendar(Object value, Calendar defaultValue) {
        Calendar result = (Calendar) converters.get(Calendar.class).convert(value);
        if (result == null) {
            return defaultValue;
        }
        return result;
    }

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ BigInteger

    /**
     * BigInteger
     *
     * @param value 需要处理的值
     * @return 转换后的值
     */
    public static BigInteger toBigInteger(Object value) {
        return (BigInteger) converters.get(BigInteger.class).convert(value);
    }

    /**
     * BigInteger
     *
     * @param value        需要处理的值
     * @param defaultValue 默认值
     * @return 转换后的值
     */
    public static BigInteger toBigInteger(Object value, BigInteger defaultValue) {
        BigInteger result = (BigInteger) converters.get(BigInteger.class).convert(value);
        if (result == null) {
            return defaultValue;
        }
        return result;
    }

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ BigDecimal

    /**
     * BigDecimal
     *
     * @param value 需要处理的值
     * @return 转换后的值
     */
    public static BigDecimal toBigDecimal(Object value) {
        return (BigDecimal) converters.get(BigDecimal.class).convert(value);
    }

    /**
     * BigDecimal
     *
     * @param value        需要处理的值
     * @param defaultValue 默认值
     * @return 转换后的值
     */
    public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue) {
        BigDecimal result = (BigDecimal) converters.get(BigDecimal.class).convert(value);
        if (result == null) {
            return defaultValue;
        }
        return result;
    }
}
